#!/usr/bin/env python
# coding=utf-8


class Test1(object):
    pass


class Test2(Test1):
    pass


def testmeta():
    a = 2
    print type(a)
    a = 's'
    print type(a)
    print type(str)  # 类的 type 还是 type，这说明 type 定义了 python 中所有类的某些基本属性
    print type(type)
    a = Test1()
    b = Test2()
    print type(a)
    print type(b)  # type 只会返回对象的直接 type，就是定义该对象的类


'''
    instance 创建的时候会调用 __init__ 函数，类似的，
    class 创建的时候会调用 __new__ 函数。通过自定义 __new__ 函数，
    你可以在创建类的时候做些额外的事情：把这个类注册到某个地方作为记录或者后续的查询，
    给类注入一些属性，或者干脆替换成另外一个类。
'''


# class MyMetaclass(type):
#     def __init__(cls, name, bases, attrs):
#         cls.__cizixs = "Don't panic"
#         print("In MyMetaclass for {}".format(name))
#         super(MyMetaClass, cls).__init__(name, bases, attrs)


class MyMetaclass(type):
    '''
        __new__ 创建类，__init__ 初始化类。所以 __new__ 会在 __init__ 之前被调用，而且 __new__ 必须要返回新创建的类，__init__ 不需要。
    '''

    def __new__(cls, name, bases, attrs):  # 此处的cls即为class，即类
        attrs['__cizixs'] = "Don't panic"  # 它为要创建的类自动添加一个属性 __cizixs
        print("In MyMetaclass for {}".format(name))
        return super(MyMetaclass, cls).__new__(cls, name, bases, attrs)
        '''
            type 的三个参数分别是：
            name: 要生产的类名
            bases：包含所有基类的 tuple
            dict：类的所有属性，是键值对的字典
        '''


class Foo(object):
    __metaclass__ = MyMetaclass
    pass
    '''
        __new__ 函数就是类创建的时候可以使用的
        注意 __new__ 是一个 classmethod，代码中参数 cls 在这里就是 <class '__main__.MyMetaclass'>。
        只要在类的定义里指定 __metaclss__，那么这个类在创建的时候就会自动使用自定义的 metaclass，而不是系统默认的 type。
        在创建类的时候，python 会按照这样的顺序去找要使用的 metaclass：
        类定义时候的类变量 __metaclass__
        类所在MODULE（就是当前文件）里的 __metaclss__ 变量
        第一个父类定义的 __metaclas__ 变量
        系统默认的 type metaclass
    '''


if __name__ == '__main__':
    testmeta()
    print "################################################"
    foo = Foo()
    print foo.__cizixs
